package com.aricwang.easyprofile.rule;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RadioGroup;
import android.widget.SimpleAdapter;
import android.widget.SimpleCursorAdapter;
import android.widget.Spinner;
import android.widget.TimePicker;

import com.aricwang.easyprofile.R;
import com.aricwang.easyprofile.contentprovider.PlaceContentProvider;
import com.aricwang.easyprofile.contentprovider.ProfileContentProvider;
import com.aricwang.easyprofile.database.PlaceTable;
import com.aricwang.easyprofile.database.ProfileTable;
import com.aricwang.easyprofile.place.Place;
import com.aricwang.easyprofile.profile.Profile;
import com.aricwang.easyprofile.service.ProfileService;

public class RuleActivity extends ListActivity {
	private static final int DIALOG_WARNING 	= 1;
	private static final int DIALOG_NAME 		= 2;
	private static final int DIALOG_TIMEFRAME 	= 3;
	private static final int DIALOG_CHARGING 	= 4;
	private static final int DIALOG_PLACE 		= 5;
	private static final int DIALOG_PROFILE		= 6;
	
	private int mRequest;
	private String mWarning = new String();

	private Rule mRule;
	
	private SimpleAdapter mAdapter = null;

	/////////////////////////////////////////////////////////////////////////////////////////
	// Static functions 
	/////////////////////////////////////////////////////////////////////////////////////////

	static void startActivity(Activity activity, int request, int ruleId, String ruleName) {
		Intent intent = new Intent().setClass(activity, RuleActivity.class);
		intent.putExtra("Request", request);
		intent.putExtra("RuleId", ruleId);
		intent.putExtra("RuleName", ruleName);
		activity.startActivityForResult(intent, request);
	}

	/////////////////////////////////////////////////////////////////////////////////////////
	// Public functions 
	/////////////////////////////////////////////////////////////////////////////////////////
	
	// set the warning string which will be shown by warning dialog
	public void setWarning(int stringId) {
		mWarning = getString(stringId);
	}
	
	// update the ListAdapter with the current data
	public void updateListAdapter() {
		String[] from = new String[]{"title", "info", "more"};
        int to[] = new int[]{R.id.title, R.id.info, R.id.more};
        mAdapter = new SimpleAdapter(this, getData(), 
        		R.layout.rule_details_row, from, to);
		
        setListAdapter(mAdapter);
	}


	/////////////////////////////////////////////////////////////////////////////////////////
	// Override functions 
	/////////////////////////////////////////////////////////////////////////////////////////

	public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        initMembers();
        setContentView(R.layout.list_details);
		updateListAdapter();
    }
	
	protected void onListItemClick(ListView l, View v, int position, long id) {
		switch(position) {
		case 0:		// rule name edit
			showDialog(DIALOG_NAME);
			break;
		case 1:		
			showDialog(DIALOG_TIMEFRAME);
			break;
		case 2:
			showDialog(DIALOG_CHARGING);
			break;
		case 3:
			showDialog(DIALOG_PLACE);
			break;
		case 4:
			showDialog(DIALOG_PROFILE);
			break;
		default:
			break;
		}
		
		mAdapter.notifyDataSetChanged();
	}
		
	protected Dialog onCreateDialog(int id) {
	    Dialog dialog = null;
        switch(id) {
	    case DIALOG_WARNING:
	    	dialog = createDialogWarning();
	    	break;
	    	
	    case DIALOG_NAME:
            dialog = createDialogName();	
	        break;
	        
	    case DIALOG_TIMEFRAME:
	    	dialog = createDialogTimeframe();
	    	break;
	        
	    case DIALOG_CHARGING:
	    	dialog = createDialogCharging();
	    	break;

	    case DIALOG_PLACE:
	    	dialog = createDialogPlace();
	    	break;

	    case DIALOG_PROFILE:
	    	dialog = createDialogProfile();
	    	break;

	    default:
	    	break;
	    }
	    
	    return dialog;
	}

	protected void onPrepareDialog(int id, Dialog dialog) {
	    switch(id) {
	    default:
	    	break;
	    }
	}
	
	/////////////////////////////////////////////////////////////////////////////////////////
	// OnClickListener interface implementation
	// handle the click event of the buttons on this page: save and cancel
	/////////////////////////////////////////////////////////////////////////////////////////
	public void onClick(View v) {
		int id = v.getId();
		
		switch(id) {
		case R.id.btn_save:
			saveRule();
			ProfileService.notifyConfigChanged(this);
			setResult(RESULT_OK);
			break;
		case R.id.btn_cancel:
			setResult(RESULT_CANCELED);
			break;
		default:
			break;
		}
		
		finish();
	}
	
		
	/////////////////////////////////////////////////////////////////////////////////////////
	// Private functions 
	/////////////////////////////////////////////////////////////////////////////////////////
	
	
	private void initMembers() {
        mRequest = RuleListActivity.REQ_ADD;

        Intent intent = getIntent();
        if (intent == null || intent.getExtras() == null) {
        	return;
        }
        
    	mRequest = intent.getExtras().getInt("Request");

    	switch(mRequest) {
        case RuleListActivity.REQ_ADD:
        	mRule = new Rule();
        	mRule.mRuleName = intent.getExtras().getString("RuleName");
        	mRule.mPriority = Rule.getNewRulePriority(this);
        	break;
       
        case RuleListActivity.REQ_EDIT:
        case RuleListActivity.REQ_COPY:
        	int id = intent.getExtras().getInt("RuleId");
        	
        	mRule = Rule.getRule(this, id);

			if (mRule != null && mRequest == RuleListActivity.REQ_COPY) {
				mRule.mRuleName = "Copy of " + mRule.mRuleName;
				mRule.mPriority = Rule.getNewRulePriority(this);
			}
        	break;
       
        default:
        	break;
        }
	}
	
	// a helper function for getData
	private void addDataToList(List<Map<String, Object>>list, String title, String info) {
		if (list == null)
			return;
		
		Map<String, Object> map;

		map = new HashMap<String, Object>();
        map.put("title", title);
        map.put("info", info);
        map.put("more", android.R.drawable.ic_menu_more);
        
        list.add(map);

        return;
	}
	
	// get rule data from content provider.
	// if request is ProfileListActivity.REQ_ADD_PROFILE, use profileName to create one;
	// if request is ProfileListActivity.REQ_EDIT_PROFILE, use profileId to retrieve the data;
	// TODO: replace the strings here with resouce ids
	private List<Map<String, Object>> getData() {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		
		if (mRule != null) {
			// list position: 0, rule name
			addDataToList(list, "Rule Name", mRule.mRuleName);
			String info;
			
			// list position: 1, timeframe condition
			if ((mRule.mRepeat & Rule.WEEK) > 0) {
				info = String.format("%02d:%02d ~ %02d:%02d\n", 
						mRule.mStartHour, mRule.mStartMinute, mRule.mEndHour, mRule.mEndMinute);
				if ((mRule.mRepeat & Rule.MON) > 0)
					info += "Mon ";
					
				if ((mRule.mRepeat & Rule.TUE) > 0)
					info += "Tue ";
		
				if ((mRule.mRepeat & Rule.WED) > 0)
					info += "Wen ";
		
				if ((mRule.mRepeat & Rule.THU) > 0)
					info += "Thu ";
		
				if ((mRule.mRepeat & Rule.FRI) > 0)
					info += "Fri ";
		
				if ((mRule.mRepeat & Rule.SAT) > 0)
					info += "Sat ";
		
				if ((mRule.mRepeat & Rule.SUN) > 0)
					info += "Sun ";
			} else {
				info = "no timeframe defined";
			}
			addDataToList(list, "Timeframe", info);
			
			// list position: 2, charging condition
			info = (mRule.mCharging == Rule.CHARGING) ? "when charging" : 
						(mRule.mCharging == Rule.NOT_CHARGING) ? "when not charging" : "don't care";
			addDataToList(list, "Charging", info);
			
			// list position: 3, place condition
			if (mRule.mPlaceId != Rule.NO_PLACE) {
				info = Place.getPlaceNameById(this, mRule.mPlaceId);
			} else {
				info = "Any place";
			}
			addDataToList(list, "Place", info);
			
			// list position: 4, profile to apply
			if (mRule.mProfileId > 0) {
				info = Profile.getProfileNameById(this, mRule.mProfileId);
			} else {
				info = "no profile defined";
			}
			addDataToList(list, "Profile to Apply", info);
		}
		
        return list;
	}

	// save the rule data to database
	private void saveRule() {
		if (mRequest == RuleListActivity.REQ_EDIT) {
			// for edit, update the existing record
			Rule.updateRule(this, mRule);
		} else {
			// for add or copy, insert the new record
			Rule.insertRule(this, mRule);
		}
		
	}

	// dialog warning creator
	private Dialog createDialogWarning() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        
        builder.setMessage(mWarning)
            .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                	dialog.dismiss();
                }
            });
        
        return builder.create();
	}

	// dialog name creator
	private Dialog createDialogName() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);

        LayoutInflater factory = LayoutInflater.from(this);
        View dialogView = factory.inflate(R.layout.dialog_edit_text, null);
        final EditText editText = (EditText)dialogView.findViewById(R.id.edit_text);
        editText.setText(mRule.mRuleName);
        
        builder.setTitle(R.string.rule_name)
            .setView(dialogView)
            .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                	// use dialogView to find the EditText????
                	String name = editText.getText().toString();
                	
                	if (name.length() <= 0) {
                    	// if name is empty, warn user
                		RuleActivity.this.setWarning(R.string.warning_rule_name_empty);
                		RuleActivity.this.showDialog(RuleActivity.DIALOG_WARNING);
                	} else {
            			// save the profile name
                		mRule.mRuleName = name;
                		updateListAdapter();
                	}

                	dialog.dismiss();
                }
            })
            .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                	dialog.cancel();
                }
            });
        
        return builder.create();	
	}

	// dialog timeframe creator
	private Dialog createDialogTimeframe() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        
        LayoutInflater factory = LayoutInflater.from(this);
        final View dialogView = factory.inflate(R.layout.dialog_rule_timeframe, null);
        
        final TimePicker start = (TimePicker)dialogView.findViewById(R.id.timeframe_start);
        final TimePicker end = (TimePicker)dialogView.findViewById(R.id.timeframe_end);
        final CheckBox sunday = (CheckBox)dialogView.findViewById(R.id.sunday);
        final CheckBox monday = (CheckBox)dialogView.findViewById(R.id.monday);
        final CheckBox tuesday = (CheckBox)dialogView.findViewById(R.id.tuesday);
        final CheckBox wednesday = (CheckBox)dialogView.findViewById(R.id.wednesday);
        final CheckBox thursday = (CheckBox)dialogView.findViewById(R.id.thursday);
        final CheckBox friday = (CheckBox)dialogView.findViewById(R.id.friday);
        final CheckBox saturday = (CheckBox)dialogView.findViewById(R.id.saturday);
        
        start.setIs24HourView(true);
        start.setCurrentHour(mRule.mStartHour);
        start.setCurrentMinute(mRule.mStartMinute);
        
        end.setIs24HourView(true);
        end.setCurrentHour(mRule.mEndHour);
        end.setCurrentMinute(mRule.mEndMinute);
        
        sunday.setChecked((mRule.mRepeat & Rule.SUN) > 0);
        monday.setChecked((mRule.mRepeat & Rule.MON) > 0);
        tuesday.setChecked((mRule.mRepeat & Rule.TUE) > 0);
        wednesday.setChecked((mRule.mRepeat & Rule.WED) > 0);
        thursday.setChecked((mRule.mRepeat & Rule.THU) > 0);
        friday.setChecked((mRule.mRepeat & Rule.FRI) > 0);
        saturday.setChecked((mRule.mRepeat & Rule.SAT) > 0);
        
        builder.setTitle(R.string.timeframe)
        .setView(dialogView)
        .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
            	mRule.mStartHour = start.getCurrentHour();
            	mRule.mStartMinute = start.getCurrentMinute();
            	mRule.mEndHour = end.getCurrentHour();
            	mRule.mEndMinute = end.getCurrentMinute();
            	
            	mRule.mRepeat = 0;
            	mRule.mRepeat |= (sunday.isChecked() ? Rule.SUN : 0);
            	mRule.mRepeat |= (monday.isChecked() ? Rule.MON : 0);
            	mRule.mRepeat |= (tuesday.isChecked() ? Rule.TUE : 0);
            	mRule.mRepeat |= (wednesday.isChecked() ? Rule.WED : 0);
            	mRule.mRepeat |= (thursday.isChecked() ? Rule.THU : 0);
            	mRule.mRepeat |= (friday.isChecked() ? Rule.FRI : 0);
            	mRule.mRepeat |= (saturday.isChecked() ? Rule.SAT : 0);
            	
           		updateListAdapter();
            	dialog.dismiss();
            }
        })
        .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
            	dialog.cancel();
            }
        });

        return builder.create();
	}

	private Dialog createDialogCharging() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);

        LayoutInflater factory = LayoutInflater.from(this);
        final View dialogView = factory.inflate(R.layout.dialog_rule_charging, null);
        final RadioGroup charging = (RadioGroup)dialogView.findViewById(R.id.radio_group_charging);
        charging.check(ChargingToRadioId(mRule.mCharging));
        
        builder.setTitle(R.string.charging)
            .setView(dialogView)
            .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                	mRule.mCharging = RadioIdToCharging(charging.getCheckedRadioButtonId());
                	
            		updateListAdapter();
                	dialog.dismiss();
                }
            })
            .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                	dialog.cancel();
                }
            });
        
        return builder.create();	
	}

	private Dialog createDialogPlace() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);

        LayoutInflater factory = LayoutInflater.from(this);
        View dialogView = factory.inflate(R.layout.dialog_spinner, null);
    	final Spinner spinner = (Spinner)dialogView.findViewById(R.id.spinner);
		
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, 
        		android.R.layout.simple_spinner_item, getPlaceSpinnerData());
		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
	    spinner.setAdapter(adapter);
	    spinner.setOnItemSelectedListener(new PlaceSpinnerOnItemSelectedListener());

	    String placeName = Place.getPlaceNameById(this, mRule.mPlaceId);
		for(int pos = 0; pos < adapter.getCount(); pos++) {
			String name = adapter.getItem(pos);
			if (name.equals(placeName)) {
				spinner.setSelection(pos);
				break;
			}
		}
        
        builder.setTitle(R.string.place)
            .setView(dialogView)
            .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
            		updateListAdapter();
                	dialog.dismiss();
                }
            })
            .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                	dialog.cancel();
                }
            });
        
        return builder.create();	
	}

	private Dialog createDialogProfile() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);

        LayoutInflater factory = LayoutInflater.from(this);
        View dialogView = factory.inflate(R.layout.dialog_spinner, null);
    	final Spinner spinner = (Spinner)dialogView.findViewById(R.id.spinner);

    	Cursor cursor = getContentResolver().query(ProfileContentProvider.CONTENT_URI, 
				new String[] { ProfileTable.COLUMN_ID, ProfileTable.COLUMN_NAME}, null, null, null);
		startManagingCursor(cursor);
		SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, 
				android.R.layout.simple_spinner_item, 
				cursor, 
				new String[] {ProfileTable.COLUMN_NAME}, 
				new int[] {android.R.id.text1});
		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);	
	    spinner.setAdapter(adapter);
	    spinner.setOnItemSelectedListener(new ProfileSpinnerOnItemSelectedListener());
	    
        cursor.moveToFirst();
        for(int pos = 0; pos < cursor.getCount(); pos++) {
        	int id = cursor.getInt(cursor.getColumnIndex(ProfileTable.COLUMN_ID));
        	if (id == mRule.mProfileId) {
        		spinner.setSelection(pos);
        		break;
        	}
        	cursor.moveToNext();
        }
        
        builder.setTitle(R.string.profile_to_apply)
            .setView(dialogView)
            .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
            		updateListAdapter();
                	dialog.dismiss();
                }
            })
            .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                	dialog.cancel();
                }
            });
        
        return builder.create();	
	}
	
	private int ChargingToRadioId(int charging) {
		int id = R.id.radio_dont_care;
		
		switch(charging) {
		case Rule.CHARGING:
			id = R.id.radio_charging;
			break;
		case Rule.NOT_CHARGING:
			id = R.id.radio_not_charging;
			break;
		case Rule.DONT_CARE:
			id = R.id.radio_dont_care;
			break;
		default:
			break;
		}
		
		return id;
	}
	
	private int RadioIdToCharging(int id) {
		int charging = Rule.DONT_CARE;
		
		switch(id) {
		case R.id.radio_charging:
			charging = Rule.CHARGING;
			break;
		case R.id.radio_not_charging:
			charging = Rule.NOT_CHARGING;
			break;
		case R.id.radio_dont_care:
			charging = Rule.DONT_CARE;
			break;
		default:
			break;
		}
		
		return charging;
	}

	private List<String> getPlaceSpinnerData() {
		List<String> list = new ArrayList<String>();
		
		list.add("Any place");
		
    	Cursor cursor = getContentResolver().query(PlaceContentProvider.CONTENT_URI, 
				new String[] { PlaceTable.COLUMN_ID, PlaceTable.COLUMN_NAME}, null, null, null);
    	
    	if (cursor != null) {
    		cursor.moveToFirst();
    		for(int i = 0; i < cursor.getCount(); i++) {
    			String name = cursor.getString(cursor.getColumnIndex(PlaceTable.COLUMN_NAME));
    			
    			list.add(name);
    			
    			cursor.moveToNext();
    		}
    	}
    	
		return list;
	}
	
	/////////////////////////////////////////////////////////////////////////////////////////
	// Inner classes
	/////////////////////////////////////////////////////////////////////////////////////////

	private class ProfileSpinnerOnItemSelectedListener implements OnItemSelectedListener {

	    public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
	    	mRule.mProfileId = (int)id;
	    }

	    public void onNothingSelected(AdapterView parent) {
	    	// Do nothing.
	    }
	}

	private class PlaceSpinnerOnItemSelectedListener implements OnItemSelectedListener {

	    public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
	    	String name = (String)parent.getAdapter().getItem(pos);
	    	int pid = Place.getPlaceIdByName(RuleActivity.this, name);
	    	mRule.mPlaceId = pid;
	    }

	    public void onNothingSelected(AdapterView parent) {
	    	// Do nothing.
	    }
	}
}
